﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Media;
using System.Windows.Forms;
using static System.Windows.Forms.Control;

namespace WindowsFormsApp2
{
    enum Direction
    {
        Up = 0,
        Right = 1,
        Down = 2,
        Left = 3
    }
    class Game
    {
        //复活位置
        private Point RevivePoint = new Point(6, 9);
        public List<PictureBox> LifePicBoxList = new List<PictureBox>();//存放游戏
        //初始生命值个数
        public int LifeCount { get; set; } = 3;
        public bool isShowGameOver = false;//是否游戏结束
        //定义游戏高度宽度
        private const int GameWidth = 2000;
        private const int GameHeight = 1200;
        //定义矩阵行列
        private const int Rows = 12;
        private const int Cols = 20;
        //定义
        private object objLifeLock = new object();
        //定义方向
        private Direction Direction { get; set; }
        private List<Block> Blocks { get; set; }
        //定义时钟
        private Timer _Timer { get; set; }
        //定义下次移动时间
        private DateTime nextStep { get; set; }
        //定义怪物集合
        private List<Monster> Monsters { get; set; }
        private List<Monster1> Monster1s { get; set; }

        //定义委托
        public delegate void GameChanged();
        public delegate void GameOver();
        //定义事件
        public event GameChanged gameChanged;
        public event GameOver gameOver;

        /// <summary>
        /// 初始化
        /// </summary>
        public Game(string map)
        {
            //初始生命值
            LifeCount = 3;
            //下一次移动时间
            nextStep = System.DateTime.Now.AddSeconds(0.5);
            //初始位置向右
            Direction = Direction.Right;
            //初始化Blocks
            Blocks = new List<Block>();
            //var map = Properties.Resources.map2;
            //初始化矩阵
            var lines = map.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < lines.Length; i++)
            {
                var items = lines[i].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                for (int j = 0; j < items.Length; j++)
                {
                    Blocks.Add(new Block(new Point(i, j), (MapType)System.Enum.Parse(typeof(MapType), items[j])));
                }
            }
            //生成第一种怪物
            Monsters = new List<Monster>();
            Monsters.Add(new Monster(1));
            Monsters.Add(new Monster(2));
            //s生成第二种怪物
            Monster1s = new List<Monster1>();
            Monster1s.Add(new Monster1(1));
            Monster1s.Add(new Monster1(2));
            //初始化时钟
            _Timer = new Timer();

            _Timer.Tick += Timer_Elapsed;
            _Timer.Start();
        }

        /// <summary>
        /// 初始化生命值
        /// </summary>
        /// <param name="controlCollection"></param>
        public void InitGame(ControlCollection controlCollection)
        {
            LifePicBoxList.Clear();//清空
            foreach (Control item in controlCollection)//所有picturebox控件集合
            {
                if (item is PictureBox)
                {
                    item.Visible = true;
                    LifePicBoxList.Add(item as PictureBox);
                }
            }
            LifePicBoxList = LifePicBoxList.OrderBy(p => { return p.Name[p.Name.Length - 1]; }).ToList();
            LifeCount = 3;
            isShowGameOver = false;
        }
        /// <summary>
        /// 时钟
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Timer_Elapsed(object sender, EventArgs e)
        {
            _Timer.Stop();//时钟停止
            MonstersMove();
            Monster1sMove();
            FoodOver();//食物耗尽产生新食物

            //通知formmain游戏改变了
            gameChanged?.Invoke();

            _Timer.Start();
        }
        /// <summary>
        /// 判断是否游戏结束
        /// </summary>
        private void IsGameOver()
        {
            if (!Blocks.Any(m => m.MapType == MapType.Player))
            {
                gameOver();
            }
        }
        /// <summary>
        /// 判断食物是否吃光并产生新食物
        /// </summary>
        public void FoodOver()
        {
            if (!Blocks.Any(m => m.MapType == MapType.Money))//矩阵中不含金币这一元素
            {
                Random random = new Random();
                //获取全部空地坐标
                var emptyBlocks = Blocks.Where(m => m.MapType == MapType.Space);
                var count = emptyBlocks.Count();
                var i = random.Next(0, count);//随机生成0到所有空地数目之间的一个数
                var j = random.Next(0, count);
                emptyBlocks.ToList()[i].MapType = MapType.Money;//在空地坐标上生成金币
                emptyBlocks.ToList()[j].MapType = MapType.Money;
            }
        }

        /// <summary>
        /// 绘制游戏区域
        /// </summary>
        /// <param name="g"></param>
        /// <param name="size"></param>
        public void Draw(Graphics g, Size size)
        {
            Image img = new Bitmap(GameWidth, GameHeight);
            Graphics _g = Graphics.FromImage(img);
            foreach (var block in Blocks)
            {
                block.Draw(_g, Direction);
            }
            g.DrawImage(img, new Rectangle(0, 0, size.Width, size.Height));
        }

        /// <summary>
        /// 键盘控制小人移动
        /// </summary>
        /// <param name="key"></param>
        public void KeyDown(string key)
        {
            Direction nextDirection = Direction.Right;//定义当前方向始终向右
            switch (key)//键盘控制方向转换
            {
                case "A":
                    nextDirection = Direction.Left;
                    break;
                case "W":
                    nextDirection = Direction.Up;
                    break;
                case "S":
                    nextDirection = Direction.Down;
                    break;
            }
            if (nextDirection != Direction)
            {
                Direction = nextDirection;
            }
            else
            {
                var player = Blocks.FirstOrDefault(m => m.MapType == MapType.Player);
                if (player == null)
                    return;
                Point pointNow = player.Point;
                Point pointNext = new Point(pointNow.X, pointNow.Y + 1);
                switch (key)//坐标变换
                {
                    case "A":
                        pointNext = new Point(pointNow.X, pointNow.Y - 1);
                        break;
                    case "W":
                        pointNext = new Point(pointNow.X - 1, pointNow.Y);
                        break;
                    case "S":
                        pointNext = new Point(pointNow.X + 1, pointNow.Y);
                        break;
                }
                //lamda expression
                var nextBlock = Blocks.FirstOrDefault(m => m.Point == pointNext);
                if (nextBlock == null)
                    return;
                if (nextBlock.MapType == MapType.Wall)//下一块是墙什么都不干
                    return;
                //todo 
                //吃金币
                if (nextBlock.MapType == MapType.Money)//碰到金币
                {
                    nextBlock.MapType = MapType.Space;
                    //添加吃金币音效
                    SoundPlayer soundPlayer = new SoundPlayer(Properties.Resources.得到金币);
                    soundPlayer.Play();
                }
                if (nextBlock.MapType == MapType.Monster1 || nextBlock.MapType == MapType.Monster)
                {
                    isControlSub = true;
                    SubLifes();
                    //回到死亡复活位置
                    var rPoint = Blocks.FirstOrDefault(f => f.Point == RevivePoint);
                    rPoint.MapType = MapType.Player;
                    player.MapType = MapType.Space;
                    isControlSub = false;
                   
                    return;
                }
                //switch转换小人与下一块
                var i = player.MapType;
                player.MapType = nextBlock.MapType;
                nextBlock.MapType = i;
            }
        }

        /// <summary>
        /// 第一种怪物移动
        /// </summary>
        private void MonstersMove()
        {
            foreach (var monster in Monsters)
            {
                var locationOld = monster.Location;//定义前一个坐标
                var localtionNew = monster.Move();//下一个坐标为move函数返回的新坐标
                if (localtionNew != null)
                {
                    ChangStatus(locationOld, MapType.Space);//原位置变成空地
                    ChangStatus((Point)localtionNew, MapType.Monster);//新位置变成怪物
                }
            }

        }
        //坐标位置变换
        private void ChangStatus(Point point, MapType mapType)
        {
            var newBlock = Blocks.FirstOrDefault(m => m.Point == point);//读取下一个元素
            if (newBlock != null)
            {
                if (newBlock.MapType == MapType.Player)
                {
                    if (!isControlSub)
                        isControlSub = true;//碰到怪物
                    SubLifes();//生命改变
                    var rPoint = Blocks.FirstOrDefault(f => f.Point == RevivePoint);//小人回到死亡复活位置
                    rPoint.MapType = MapType.Player;
                    isControlSub = false;
                }
                newBlock.MapType = mapType;
            }
        }
        /// <summary>
        /// 第二种怪物移动
        /// </summary>
        private void Monster1sMove()
        {
            foreach (var monster1 in Monster1s)
            {
                var locationOld = monster1.Location;//定义前一个坐标
                var localtionNew = monster1.Move();//下一个坐标为move函数返回的新坐标
                if (localtionNew != null)
                {
                    ChangStatus1(locationOld, MapType.Space);
                    ChangStatus1((Point)localtionNew, MapType.Monster1);
                }
            }

        }
       //第二种怪物坐标位置变换
        private void ChangStatus1(Point point, MapType mapType)
        {
            var newBlock = Blocks.FirstOrDefault(m => m.Point == point);//读取下一个元素
            if (newBlock != null)
            {
                if (newBlock.MapType == MapType.Player)
                {
                    if (!isControlSub)
                        isControlSub = true;//碰到怪物
                    SubLifes();
                    var rPoint = Blocks.FirstOrDefault(f => f.Point == RevivePoint);//小人回到死亡复活位置
                    rPoint.MapType = MapType.Player;
                    isControlSub = false;
                }
                newBlock.MapType = mapType;
            }
        }
        bool isControlSub = false;//定义是否碰到怪物
        /// <summary>
        /// 生命值改变函数
        /// </summary>
        private void SubLifes()
        {
            if (isControlSub)//布尔值为true碰到怪物
            {
                lock (objLifeLock)//固定生命参数
                {
                    //判断生命值耗尽游戏结束
                    if (LifePicBoxList.Count == 0)
                    {
                      
                        gameOver?.Invoke();//?.null检查运算符
                        
                    }
                    //游戏未结束生命值减一
                    else
                    {
                        LifeCount--;
                        var pic = LifePicBoxList[LifeCount];//读取生命值

                        pic.Visible = false;
                        LifePicBoxList.RemoveAt(LifeCount);//移走一个生命值
                        if (LifeCount <= 0)//生命值减为零游戏判断游戏结束
                        {
                            gameOver?.Invoke();
                        }
                    }
                }
            }
        }
    }
}

